home *** CD-ROM | disk | FTP | other *** search
/ Palm Pilot Collection / Palm Pilot Collection (Explore the World of Software) (1998).iso / apps / mathpad.exe / MPEXPORT.C < prev    next >
C/C++ Source or Header  |  1997-09-28  |  6KB  |  189 lines

  1. /* MpExport: Exports the records from a backed up MathPad database file
  2.  * to a simple ASCII text file so they can be given/emailed to others,
  3.  * edited with your favorite text editor, printed, etc.  Use MpImport
  4.  * to import the text records back into your MathPad database file.
  5.  *
  6.  * Written in plain vanilla ANSI standard C; should compile pretty easily
  7.  * with any regular C compiler.  Released to the public domain.
  8.  *
  9.  * Version 1.0, 28 Sep 1997, Rick Huebner
  10.  */
  11. #include <stddef.h>
  12. #include <stdlib.h>
  13. #include <stdio.h>
  14. #include <string.h>
  15.  
  16. #include "mpdb.h"
  17.  
  18.  
  19.  
  20. void main(int argc, char *argv[]) {
  21.    FILE *db, *text;
  22.    size_t length;
  23.    long listpos;
  24.    Word recnum;
  25.    Byte catnum;
  26.    Boolean secret;
  27.    int c;
  28.    DatabaseHdrType hdr;
  29.    AppInfoType info;
  30.    RecordListType reclist;
  31.    RecordEntryPtr entries, entryptr;
  32.    MathPadItemType item;
  33.  
  34.    /* Check for the proper command line format */
  35.    if (argc != 3) {
  36.       puts("Format: MPEXPORT DbFileName TextFileName");
  37.       exit(1);
  38.    }
  39.  
  40.    /* Open the MathPad database file to be read.  NOTE: "rb"
  41.       indicates "binary" file type with no CR/LF text translation.
  42.       You may need to change this to "r" if "rb" isn't supported
  43.       by your compiler, but call setmode() or whatever as required
  44.       to make sure no translations are done for this file. */
  45.    db = fopen(argv[1], "rb");
  46.    if (!db) {
  47.       printf("Can't open \"%s\": %s", argv[1], strerror(errno));
  48.       exit(1);
  49.    }
  50.  
  51.    /* Open the text file to be written.  If CR/LF text translations
  52.       are required for your system, they should be enabled here.
  53.       Text translations are on by default under Microsoft C, and
  54.       will write all '\n' characters as a CR/LF pair.  Translations
  55.       aren't needed under Unix.  I don't know about Macs. */
  56.    text = fopen(argv[2], "w");
  57.    if (!text) {
  58.       printf("Can't open \"%s\": %s", argv[2], strerror(errno));
  59.       exit(1);
  60.    }
  61.  
  62.    /* Read the database header */
  63.    length = offsetof(DatabaseHdrType, recordList);
  64.    if (fread(&hdr, 1, length, db) != length) {
  65.       perror("Error reading database header");
  66.       exit(1);
  67.    }
  68.  
  69.    /* Make sure we know how to handle this database file */
  70.    if (strncmp((char *)&hdr.type, MathPadType, 4) || strncmp((char *)&hdr.creator, MathPadCreator, 4)) {
  71.       puts("Not a MathPad database file");
  72.       exit(1);
  73.    }
  74.  
  75.    SwapWord(&hdr.version);
  76.    if (hdr.version != MathPadVersion) {
  77.       puts("Don't know how to read this version of MathPad database.");
  78.       puts("Please get the latest version of MpExport and try again.");
  79.       exit(1);
  80.    }
  81.  
  82.    /* Remember our current file position so we can come back here
  83.       to read the (first?) record list header. */
  84.    listpos = ftell(db);
  85.  
  86.    /* Go to and read the app info block (category data). */
  87.    SwapDWord(&hdr.appInfoID);
  88.    fseek(db, hdr.appInfoID, SEEK_SET);
  89.    if (fread(&info, 1, sizeof(info), db) != sizeof(info)) {
  90.       perror("Error reading database app info block");
  91.       exit(1);
  92.    }
  93.  
  94.    /* Process the linked list of record lists */
  95.    do {
  96.       /* Go to and read this record list header */
  97.       fseek(db, listpos, SEEK_SET);
  98.       length = offsetof(RecordListType, firstEntry);
  99.       if (fread(&reclist, 1, length, db) != length) {
  100.          perror("Error reading database record list");
  101.          exit(1);
  102.       }
  103.  
  104.       SwapWord(&reclist.numRecords);
  105.       if (reclist.numRecords > 0) {
  106.          /* Allocate memory for the correct size array of record entries */
  107.          length = reclist.numRecords * sizeof(RecordEntryType);
  108.          entries = malloc(length);
  109.          if (!entries) {
  110.             perror("malloc() failure");
  111.             exit(1);
  112.          }
  113.  
  114.          /* Read the record list entries into our array */
  115.          if (fread(entries, 1, length, db) != length) {
  116.             perror("Error reading database record entries");
  117.             exit(1);
  118.          }
  119.  
  120.          /* Export each record in the record entry array */
  121.          for (entryptr = entries, recnum = 0; recnum < reclist.numRecords; ++recnum, ++entryptr) {
  122.             /* Extract the category number and Secret flag from this entry */
  123.             catnum = entryptr->attributes & dmRecAttrCategoryMask;
  124.             secret = (entryptr->attributes & dmRecAttrSecret) != 0;
  125.  
  126.             /* Go to this record in the file */
  127.             SwapDWord(&entryptr->localChunkID);
  128.             fseek(db, entryptr->localChunkID, SEEK_SET);
  129.  
  130.             /* Read the MathPad record header */
  131.             length = offsetof(MathPadItemType, text);
  132.             if (fread(&item, 1, length, db) != length) {
  133.                perror("Error reading database record");
  134.                exit(1);
  135.             }
  136.  
  137.             /* Print the record settings */
  138.             fprintf(text, CategoryLine, info.categoryLabels[catnum], secret);
  139.             fprintf(text, PlacesLine, item.places, item.stripzeros);
  140.  
  141.             /* Print the record text */
  142.             while ((c = fgetc(db)) > 0)
  143.                fputc(c, text);
  144.             fputc('\n', text);
  145.  
  146.             fputs(SeparatorLine, text);
  147.          }
  148.  
  149.          /* Free this record entry array */
  150.          free(entries);
  151.       }
  152.  
  153.       /* Get the position of the next record list in the chain, if any */
  154.       SwapDWord(&reclist.nextRecordListID);
  155.       listpos = reclist.nextRecordListID;
  156.    } while (listpos);
  157.  
  158.    /* All done; clean up and exit */
  159.    fclose(text);
  160.    fclose(db);
  161. }
  162.  
  163.  
  164.  
  165. /* Routines to translate a value between Motorola-style storage format 
  166.  * (MSB first) and Intel-style storage format (LSB first).
  167.  */
  168. #ifdef LITTLE_ENDIAN
  169. void SwapWord(void *p) {
  170.    Byte *bp = (Byte *)p, temp;
  171.  
  172.    temp = bp[0];
  173.    bp[0] = bp[1];
  174.    bp[1] = temp;
  175. }
  176.  
  177.  
  178.  
  179. void SwapDWord(void *p) {
  180.    Word *wp = (Word *)p, temp;
  181.  
  182.    temp = wp[0];
  183.    wp[0] = wp[1];
  184.    wp[1] = temp;
  185.    SwapWord(wp);
  186.    SwapWord(wp+1);
  187. }
  188. #endif   
  189.